<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="../0_assets/vue2.js"></script>
</head>

<body>
    <div id="app">
        <h2>{{ message }}</h2>
        <father></father>
    </div>

    <script>
        /*
            父子组件之间的通信，跨级通信  provide/inject
            provide(提供)，是一个对象或者一个返回对象的函数
            inject(注入)，可以是一个字符串的数组也可以是一个对象，在需要使用的地方注入即可
        */
        let app = new Vue({
            el: '#app',
            data() {
                return {
                    message: '我是爷爷组件',
                }
            },
            // provide其实就像data一样，return出去一个对象，里面以属性名和值对应的形式呈现出你想让子孙们获取到的数据
            provide() {
                return {
                    grandpamessage: this.message,
                    // 下面这种可以让provide中的数据成为响应式，因为他直接把自身实例给出去了
                    grandpa: this,

                }
            },
            watch: {
                message() {
                    console.log('有人修改爷爷组件中的message');
                }
            },
            components: {
                father: {
                    template: `<div><h4>爸爸组件</h4><son></son></div>`,
                    // inject的使用也很简单，像props的简单形式一样，用属性名组成一个数组即可
                    inject: ['grandpamessage','grandpa'],
                    mounted() {
                        // 直接this.xxx就可以获取到了
                        console.log('爸爸组件: ', this.grandpamessage);

                        // 但是有一个问题要注意到，就是provide和inject之间共享的数据不是响应式的，也就是说，你在子组件里修改祖先组件给你的数据，不会影响祖先组件的数据本身。所以vue只是复制了一个数据给子组件
                        this.grandpamessage = '11111';//你会发现你修改之后，爷爷组件那里的watch并没有触发

                        // 如果你想让共享数据成为响应式的，有一种方法，就是你在爷爷组件的provide中，直接把父组件的this给出去，相当于爷爷组件直接把自身实例给自己的后代了，这个做法极其不推荐。
                        setTimeout(() => {
                            this.grandpa.message = '儿子改爹，大逆不道。';
                        }, 1000);
                    },
                    components: {
                        son: {
                            template: `<h6>儿子组件</h6>`,
                            inject: ['grandpamessage'],
                            mounted() {
                                console.log('儿子组件：', this.grandpamessage);
                            }
                        }
                    }
                }
            }
        });
    </script>
</body>

</html>